"""
This class contain the results of test scripts execution. The result of each test script 
execution are stored in a ScriptResultManager object, that stores all of the 
ScriptResultManager objects, thus, this class is responsible for keep all the test results
of a python application.
 
@author: Gustavo Pereira
"""
from pyeasyaccept.commom.Configuration import Configuration
import os
class ResultsHandler:
    

    def __init__(self):
        self.totalPassedTestsCalculated = False
        self.totalNotPassedTestsCalculated = False
        self.__scriptsResult = dict()
        self.__scriptsCounter = dict() 
    
    
    def addResult(self, scriptResultManager):
        """
        This method adds a ScriptResultManager object
        @param scriptResultManager: The scriptResultManager object
        """  
        scriptName = scriptResultManager.getScriptName()
        if not self.__scriptsResult.has_key(scriptName):
            self.__scriptsCounter[scriptName] = 0
        self.__scriptsResult[scriptResultManager.getScriptName()] =  scriptResultManager
        self.__scriptsCounter[scriptName] = self.__scriptsCounter[scriptName] + 1
    
#= = = = = = = = = = = = = = = general results = = = = = = = = = = = = = = = = = = = = =

    def getTestLineResult(self, scriptName, line):
        """
        This method returns a Result object for a specified script line.
        @param file: the test script
        @param line: the test script line
        @return: the test result for a specified script line or None if the doesn't exist
        """
        try:       
            return self.__scriptsResult[scriptName].getLineResult(line)
        except KeyError:
            return None

    def getSummarizedResults(self):
        """
        This method returns the Summarized result of all executed tests.
        Summarized results contains: Tested scripts name, Number of passed tests and
        Number of Not passed tests.
        @return: the Summarized test result
        """
        SummarizedOut = ""
        
        for oneScript in sorted(self.__scriptsResult.keys()):
            for i in range(self.__scriptsCounter[oneScript]):
                SummarizedOut += "Test file: " + oneScript + " | Passed Tests: " + str(self.getScriptNumberOfPassedTests(oneScript)) + " | Not Passed Tests: " + str(self.getScriptNumberOfNotPassedTests(oneScript))
                SummarizedOut += os.linesep
        return SummarizedOut;
    
    def getCompleteResults(self):
        """
        This method returns a complete result of all executed tests.
        Complete result contains: Tested scripts name, Number of passed tests,
        Number of not passed tests and Erros descriptions (if it has been occurred).
        @return: the complete test result
        """        
        compResult = ""
              
        for oneScript in sorted(self.__scriptsResult.keys()):
            for i in range(self.__scriptsCounter[oneScript]):
                compResult += self.getScriptCompleteResults(oneScript)+ Configuration.WHITE_LINE_CODE
                compResult += "======================== " + Configuration.WHITE_LINE_CODE
            
        return compResult;
    
   
    def getScriptErros(self, scriptName):
        """
        This method returns the Erros of a specified test script.
        @param scriptName: the test script's name
        @return: the Erros description if it has been occurred. Otherwise returns the string "".
        """        
        failures = ""
        
        if(self.getScriptNumberOfNotPassedTests(scriptName) != 0):
            failures += "FAILURES:" + Configuration.WHITE_LINE_CODE
            
        scriptResults = self.__scriptsResult[scriptName]   
            
        for resultLine in scriptResults.getResults():
            aLineResult = scriptResults.getLineResult(resultLine) 
            if(aLineResult.getTestLineStatus() == Configuration.ERROR_CODE):
                failures += "At line "+ str(resultLine) +": " + str(aLineResult.getErrorMessage()) + os.linesep;
    
        return failures
        
    def getTotalNumberOfPassedTests(self):
        """
        This method returns the total number of passed tests
        @return: the total number of passed tests
        """        
        if(self.totalPassedTestsCalculated ):
            return self.totalPassedTests
        else:
            self.totalPassedTests = 0
            for oneScript in self.__scriptsResult:
                self.totalPassedTests += self.getScriptNumberOfPassedTests(oneScript) * self.__scriptsCounter[oneScript]
                
            self.totalPassedTestsCalculated = True
            return self.totalPassedTests
    
    def getTotalNumberOfNotPassedTests(self):
        """
        This method returns the total number of not passed tests
        @return: the total number of not passed tests
        """    
        if(self.totalNotPassedTestsCalculated):
            return self.totalNotPassedTests
        else:
            self.totalNotPassedTests = 0
            for oneScript in self.__scriptsResult:
                self.totalNotPassedTests += self.getScriptNumberOfNotPassedTests(oneScript) * self.__scriptsCounter[oneScript]
            
            self.totalNotPassedTestsCalculated = True    
            return self.totalNotPassedTests
    
    def getTotalNumTests(self):
        """
        This method returns the total number of executed tests
        @return: the total number of executed tests
        """
        return self.getTotalNumberOfPassedTests() + self.getTotalNumberOfNotPassedTests()
    
#= = = = = = = = = = = = = = = each script results= = = = = = = = = = = = = = = = = = = = =    
 
    def getScriptCompleteResults(self, scriptName):
        """
        This method returns a complete result of a specified test script.
        Complete result contains: Tested script name, Number of passed tests,
        Number of not passed tests and Erros descriptions (if it has been occurred).
        @param scriptName: the test script
        @return: the complete test result or None if there is no script with this name
        """
        if(not(self.__containsScript(scriptName))):
            return None
        return self.getScriptSummarizedResults(scriptName) + 2*Configuration.WHITE_LINE_CODE + self.getScriptErros(scriptName)

    def getScriptResults(self, scriptName):
        """
        This method returns a set of all the script Result objects.
        @return: all the test results of the test script specified
        """
        if(not(self.__containsScript(scriptName))):
            return None
        return self.__scriptsResult[scriptName].getResults()
    
    def getScriptSummarizedResults(self, scriptName):
        """
        This method returns the Summarized results of a specificied test script
        Summarized result contains: Tested script name, Number of passed tests,
        and Number of not passed tests.
        @param scriptName: the test script
        @return: the Summarized test result
        """
        if(not(self.__containsScript(scriptName))):
            return None
        summarizedOut = "Test file: " + scriptName + " | Passed Tests: " + str(self.getScriptNumberOfPassedTests(scriptName)) + " | Not Passed Tests: " + str(self.getScriptNumberOfNotPassedTests(scriptName));
        return summarizedOut;
    
    def getScriptNumberOfPassedTests(self, scriptName):
        """
        This method returns the number of passed tests of a specified test script.
        @param scriptName: the test script
        @return: the number of passed tests
        """
        if(not(self.__containsScript(scriptName))):
            return None
        return self.__scriptsResult[scriptName].getNumPassedTests()
    
    def getScriptNumberOfNotPassedTests(self, scriptName):
        """
        This method returns the number of not passed tests of a specified test script.
        @param scriptName: the test script
        @return: the number of not passed tests
        """
        if(not(self.__containsScript(scriptName))):
            return None
        return self.__scriptsResult[scriptName].getNumNotPassedTests()
    
    def getScriptTotalNumberOfTests(self, scriptName):
        """
        This method returns the total number of executed tests of a specified test script.
        @param scriptName: the test script
        @return: the total number of executed tests of a specified test script
        """
        if(not(self.__containsScript(scriptName))):
            return None
        return self.__scriptsResult[scriptName].getNumTests()
    
    def __containsScript(self, scriptName):
        return self.__scriptsResult.__contains__(scriptName)
        